module BUS(
////////////////// CLK /////////////////
CLOCK,
PRIORITY,
////////////////// SRAM/////////////////
SRAM_ADDR,
SRAM_DATA,
WE_N,
OE_N,
UB_N,
LB_N,
CE_N,
////////////////// VGA /////////////////
VGA_ADDR,
VGA_DATA,
V_SYNC,
VGA_WHICH_BYTE,
////////////////// FETCH P1////////////////
FETCH_ADDR_P1,
FETCH_DATA_OUT_P1,
FETCH_LB_P1,
FETCH_UB_P1,
WAIT_P1,
HOLD_P1,
////////////////// MEM P1////////////////
MEM_ADDR_P1,
MEM_DATA_IN_P1,
MEM_DATA_OUT_P1,
MEM_WRITE_P1,
MEM_LB_P1,
MEM_UB_P1,
MEM_ENABLE_P1,
////////////////// FETCH ////////////////
FETCH_ADDR_P2,
FETCH_DATA_OUT_P2,
FETCH_LB_P2,
FETCH_UB_P2,
WAIT_P2,
HOLD_P2,
////////////////// MEM ////////////////
MEM_ADDR_P2,
MEM_DATA_IN_P2,
MEM_DATA_OUT_P2,
MEM_WRITE_P2,
MEM_LB_P2,
MEM_UB_P2,
MEM_ENABLE_P2
);

///////////////// CLK /////////////////
input CLOCK;
output PRIORITY;
///////////////// MEM /////////////////
output [17:0] SRAM_ADDR;
inout [15:0] SRAM_DATA;
output WE_N;
output OE_N;
output UB_N;
output LB_N;
output CE_N;

///////////////// VGA //////////////////
output [7:0] VGA_DATA;
input [17:0] VGA_ADDR;
input VGA_WHICH_BYTE; //1 = UPPER
input V_SYNC;

///////////////// FETCH P1/////////////////
input [17:0] FETCH_ADDR_P1;
output [15:0] FETCH_DATA_OUT_P1;
input FETCH_UB_P1;
input FETCH_LB_P1;
output WAIT_P1;
input HOLD_P1;
////////////////////////////////////////

//////////////// MEM P1////////////////////
input [17:0] MEM_ADDR_P1;
input [15:0] MEM_DATA_IN_P1;
output [15:0] MEM_DATA_OUT_P1;
input MEM_UB_P1;
input MEM_LB_P1;
input MEM_ENABLE_P1;
input MEM_WRITE_P1;
/////////////////////////////////////////

///////////////// FETCH P2/////////////////
input [17:0] FETCH_ADDR_P2;
output [15:0] FETCH_DATA_OUT_P2;
input FETCH_UB_P2;
input FETCH_LB_P2;
output WAIT_P2;
input HOLD_P2;
////////////////////////////////////////

//////////////// MEM P2////////////////////
input [17:0] MEM_ADDR_P2;
input [15:0] MEM_DATA_IN_P2;
output [15:0] MEM_DATA_OUT_P2;
input MEM_UB_P2;
input MEM_LB_P2;
input MEM_ENABLE_P2;
input MEM_WRITE_P2;
/////////////////////////////////////////

wire WAIT;
wire HOLD;
reg PROC_PRIORITY = 1'b0;

wire [17:0] FETCH_ADDR;
wire [15:0] FETCH_DATA_OUT;
wire FETCH_UB;
wire FETCH_LB;

wire [17:0] MEM_ADDR;
wire [15:0] MEM_DATA_IN;
wire [15:0] MEM_DATA_OUT;
wire MEM_UB;
wire MEM_LB;
wire MEM_ENABLE;
wire MEM_WRITE;

assign HOLD = HOLD_P1 | HOLD_P2;

assign FETCH_ADDR = PROC_PRIORITY ? FETCH_ADDR_P2 : FETCH_ADDR_P1;
assign FETCH_UB = PROC_PRIORITY ? FETCH_UB_P2 : FETCH_UB_P1;
assign FETCH_LB = PROC_PRIORITY ? FETCH_LB_P2 : FETCH_LB_P1;

assign MEM_ADDR = PROC_PRIORITY ? MEM_ADDR_P2 : MEM_ADDR_P1;
assign MEM_UB = PROC_PRIORITY ? MEM_UB_P2 : MEM_UB_P1;
assign MEM_LB = PROC_PRIORITY ? MEM_LB_P2 : MEM_LB_P1;
assign MEM_ENABLE = PROC_PRIORITY ? MEM_ENABLE_P2 : MEM_ENABLE_P1;
assign MEM_WRITE = PROC_PRIORITY ? MEM_WRITE_P2 : MEM_WRITE_P1;

always @(posedge CLOCK) begin
	if (!HOLD) begin
		PROC_PRIORITY = !PROC_PRIORITY;
	end	
end

assign WAIT = 0;
assign PRIORITY = PROC_PRIORITY;

assign WAIT_P1 = !WAIT & PROC_PRIORITY;
assign WAIT_P2 = !WAIT & !PROC_PRIORITY;

//assign WAIT = MEM_ENABLE ? !MEM_WRITE : 0;

assign SRAM_DATA[15:0] = (MEM_ENABLE & MEM_WRITE & !WAIT_P1)? MEM_DATA_IN_P1[15:0] : 16'hzzzz;
assign SRAM_DATA[15:0] = (MEM_ENABLE & MEM_WRITE & !WAIT_P2)? MEM_DATA_IN_P2[15:0] : 16'hzzzz;

assign MEM_DATA_OUT_P1[15:0] = (MEM_ENABLE & !MEM_WRITE & !WAIT_P1) ? SRAM_DATA[15:0] : 16'h0;
assign MEM_DATA_OUT_P2[15:0] = (MEM_ENABLE & !MEM_WRITE & !WAIT_P2) ? SRAM_DATA[15:0] : 16'h0;

//assign VGA_DATA[7:0] = ((!CE_N & !OE_N) ? ( (VGA_WHICH_BYTE)? SRAM_DATA[15:8]:SRAM_DATA[7:0])   :8'bz);

assign FETCH_DATA_OUT_P1[15:0] = (!MEM_ENABLE & !WAIT_P1) ? SRAM_DATA[15:0] : 16'h0;
assign FETCH_DATA_OUT_P2[15:0] = (!MEM_ENABLE & !WAIT_P2) ? SRAM_DATA[15:0] : 16'h0;

assign SRAM_ADDR = (!WAIT) ? ((MEM_ENABLE) ? MEM_ADDR : FETCH_ADDR) : VGA_ADDR;

assign WE_N = (MEM_ENABLE)? !MEM_WRITE: 1;
assign OE_N = (MEM_ENABLE)? MEM_WRITE: 0;
assign UB_N = !WAIT ? (MEM_ENABLE ? !MEM_UB : !FETCH_UB) : !VGA_WHICH_BYTE;
assign LB_N = !WAIT ? (MEM_ENABLE ? !MEM_LB : !FETCH_LB) : VGA_WHICH_BYTE;

assign CE_N = 0;

endmodule
